﻿using Nanolink;
using NanolinkDemo;
using System.Collections;
using UnityEngine;
using UnityEngine.Events;

namespace CoverShooter
{
    /// <summary>
    /// Takes player input and translates that to commands to CharacterMotor.
    /// </summary>
    [RequireComponent(typeof(CharacterMotor))]
    public class SelfThirdPersonInput : ThirdPersonInput
    {
        /// <summary>
        /// Camera mooved by this input component.
        /// </summary>
       
        int playerIndex = -1;

        float SynTime = 10;

        public OtherThirdPersonInput otp;

        private void Awake()
        {
            _controller = GetComponent<ThirdPersonController>();
            _motor = GetComponent<CharacterMotor>();
        }

        public bool initRole(byte playernum, Color color, string name, Vector3 pos)
        {
            m_PlayerNumber = playernum;
            //gameObject.name = name;

            return true;
        }

        void Start()
        {

        }

        float delayFireTime = 0;
        private void Update()
        {

            UpdateCamera();
            UpdateTarget();
            UpdateWeapons();
            UpdateReload();
            SelfUpdateRolling();
            UpdateFireAndZoom();
            UpdateGrenade();
            UpdateCrouching();
            SelfUpdateClimbing();
            UpdateCover();
            SelfUpdateJumping();

            UpdateMovement();


            if (Input.GetMouseButtonUp(1))
            {
                aimRelealeEvent("0");               //弹起右键后放弃瞄准
            }
            else if (Input.GetMouseButtonDown(1))
            {
                aimRelealeEvent("1");               //按下右键后开始瞄准
            }

            if (Input.GetMouseButtonUp(0))
            {
                _controller.FireInput = false;
                aimFireEvent("0");               //弹起右键后放弃开火
            }
            else if (Input.GetMouseButton(0))
            {
                if (delayFireTime < 0)
                {
                    _controller.FireInput = true;
                    _motor.Gun.isSelf = false;
                    aimFireEvent("1");               //按下右键后开始开火
                    delayFireTime = _motor.Gun.delay;
                    if (_motor.Gun.delay == 0)
                    {
                        delayFireTime = 0.5f;
                    }
                }
            }
            delayFireTime -= Time.deltaTime;
            if (SynTime > 0)
            {
                SynTime -= Time.deltaTime;
            }
            else
            {
                SynTime = 10;
                SynLocationEvent();
            }
        }

        protected virtual void SelfUpdateJumping()
        {
            if (Input.GetButtonDown("Jump"))
            {
                _motor.InputJump();
                SynJumpEvent();
            }
        }

        protected virtual void SelfUpdateRolling()
        {
            if (_timeW > 0) _timeW -= Time.deltaTime;
            if (_timeA > 0) _timeA -= Time.deltaTime;
            if (_timeS > 0) _timeS -= Time.deltaTime;
            if (_timeD > 0) _timeD -= Time.deltaTime;

            if (Input.GetButtonDown("RollForward"))
            {
                if (_timeW > float.Epsilon)
                {
                    if (_motor.IsInCover && _motor.CanClimbOrVault)
                        _motor.InputClimbOrVault();
                    else
                        _motor.InputRoll(_motor.LookAngle);
                    SynRollingEvent();
                }
                else
                    _timeW = DoubleTapDelay;
            }

            if (Input.GetButtonDown("RollLeft"))
            {
                if (_timeA > float.Epsilon)
                {
                    SynRollingEvent();
                    _motor.InputRoll(_motor.LookAngle - 90);
                }
                else
                    _timeA = DoubleTapDelay;
            }

            if (Input.GetButtonDown("RollBackward"))
            {
                if (_timeS > float.Epsilon)
                {
                    SynRollingEvent();
                    _motor.InputRoll(_motor.LookAngle + 180);
                }
                else
                    _timeS = DoubleTapDelay;
            }

            if (Input.GetButtonDown("RollRight"))
            {
                if (_timeD > float.Epsilon)
                {
                    SynRollingEvent();
                    _motor.InputRoll(_motor.LookAngle + 90);
                }
                else
                    _timeD = DoubleTapDelay;
            }
        }

        void SelfUpdateClimbing()
        {
            if (Input.GetButtonDown("Climb"))
                if (Input.GetAxis("Vertical") > 0.1f)
                    if (_motor.IsInCover && _motor.CanClimbOrVault)
                    {
                        _motor.InputClimbOrVault();
                        SynClimbingEvent();
                    }
        }

        protected virtual void UpdateFireAndZoom()
        {
            //if (Input.GetButtonDown("Fire1")) _controller.FireInput = true;
            if (Input.GetButtonDown("Fire2")) _controller.ZoomInput = true;
            //if (Input.GetButtonUp("Fire1")) _controller.FireInput = false;
            if (Input.GetButtonUp("Fire2")) _controller.ZoomInput = false;
        }

        protected virtual void UpdateWeapons()
        {
            if (Input.GetKey(KeyCode.Alpha1)) { _motor.InputCancelGrenade(); _motor.InputWeapon(0); }
            if (Input.GetKey(KeyCode.Alpha2)) { _motor.InputCancelGrenade(); _motor.InputWeapon(1); }
            if (Input.GetKey(KeyCode.Alpha3)) { _motor.InputCancelGrenade(); _motor.InputWeapon(2); }
            if (Input.GetKey(KeyCode.Alpha4)) { _motor.InputCancelGrenade(); _motor.InputWeapon(3); }
            if (Input.GetKey(KeyCode.Alpha5)) { _motor.InputCancelGrenade(); _motor.InputWeapon(4); }
            if (Input.GetKey(KeyCode.Alpha6)) { _motor.InputCancelGrenade(); _motor.InputWeapon(5); }
            if (Input.GetKey(KeyCode.Alpha7)) { _motor.InputCancelGrenade(); _motor.InputWeapon(6); }
            if (Input.GetKey(KeyCode.Alpha8)) { _motor.InputCancelGrenade(); _motor.InputWeapon(7); }
            if (Input.GetKey(KeyCode.Alpha9)) { _motor.InputCancelGrenade(); _motor.InputWeapon(8); }
            if (Input.GetKey(KeyCode.Alpha0)) { _motor.InputCancelGrenade(); _motor.InputWeapon(9); }

            if (Input.mouseScrollDelta.y < 0)
            {
                if (_motor.CurrentWeapon == 0)
                {
                    SwitchWeaponEvent();
                    _motor.InputWeapon(_motor.Weapons.Length);
                }
                else
                {
                    SwitchWeaponEvent();
                    _motor.InputWeapon(_motor.CurrentWeapon - 1);
                }
            }
            else if (Input.mouseScrollDelta.y > 0)
            {
                if (_motor.CurrentWeapon == _motor.Weapons.Length)
                {
                    SwitchWeaponEvent();
                    _motor.InputWeapon(0);
                }
                else
                {
                    SwitchWeaponEvent();
                    _motor.InputWeapon(_motor.CurrentWeapon + 1);
                }
            }
        }

        CharacterMovement movement;
        protected virtual void UpdateMovement()
        {
            movement = new CharacterMovement();

            var direction = Input.GetAxis("Horizontal") * Vector3.right +
                            Input.GetAxis("Vertical") * Vector3.forward;

            //moveEvent();

            var lookAngle = Util.AngleOfVector(_controller.LookTargetInput - _motor.transform.position);

            if (direction.magnitude > float.Epsilon)
                movement.Direction = Quaternion.Euler(0, lookAngle, 0) * direction.normalized;

            if (_controller.ZoomInput)
                movement.Magnitude = 0.5f;
            else
            {
                if (_motor.Gun != null)
                {
                    if (Input.GetButton("Run") && !_motor.IsCrouching)
                        movement.Magnitude = 2.0f;
                    else
                        movement.Magnitude = 1.0f;
                }
                else
                {
                    if (Input.GetButton("Run"))
                        movement.Magnitude = 1.0f;
                    else
                        movement.Magnitude = 0.5f;
                }
            }

            _controller.MovementInput = movement;
            Syn();
            Rotation();
            if (_controller.ZoomInput)
            {
                aimEvent();
            }
        }



        float m_synTime;
        private void Syn()
        {
            m_synTime += Time.deltaTime;

            if (m_synTime >= 0.06f)
            {
                moveEvent();
                //m_moveEvent.Invoke();
                m_synTime = 0;
            }
        }

        Vector3 LastPos;
        bool isStartMove = false;
        public void moveEvent()
        {
            if (Vector3.Distance(LastPos, transform.position) > 0)
            {
                Hashtable values = new Hashtable();
                values.Add("name", "move");
                values.Add("MoveData", movement.Magnitude + "|" + movement.Direction.x + "|" + movement.Direction.y + "|" + movement.Direction.z + "|" + transform.localEulerAngles.y);
                //values.Add("Vertical", Input.GetAxis("Vertical"));
                //values.Add("RotationY", transform.localEulerAngles.y);
                if (otp != null)
                {
                    otp.UpdateMovement(movement.Magnitude, movement.Direction);
                }
                MyClient.send(MySerialize.toBytes(values));
                LastPos = transform.position;
            }
        }

        float LastRot;
        public void Rotation()
        {
            float TempLastRot = LastRot - transform.localEulerAngles.y;
            if (TempLastRot < 0)
            {
                TempLastRot = TempLastRot * -1;
            }
            if (TempLastRot > 10)
            {
                Hashtable values = new Hashtable();
                values.Add("name", "Rotation");
                values.Add("RotData", transform.localEulerAngles.y+"");

                if (otp != null)
                {
                    otp.transform.localEulerAngles = new Vector3(0, float.Parse((string)values["RotData"]), 0);
                }
                MyClient.send(MySerialize.toBytes(values));
                LastRot = transform.localEulerAngles.y;
            }
        }

        float LastLookAngle = 0;
        public void aimEvent()
        {
            float TempLookAngle = LastLookAngle - _motor._verticalLookAngle;
            if (TempLookAngle < 0)
            {
                TempLookAngle = TempLookAngle * -1;
            }
            if (TempLookAngle > 10)
            {
                Hashtable values = new Hashtable();
                values.Add("name", "AimHeight");
                values.Add("AimData", _motor._verticalLookAngle.ToString());
                MyClient.send(MySerialize.toBytes(values));
                LastLookAngle = _motor._verticalLookAngle;
            }
        }

        public void aimFireEvent(string isFire)
        {
            Hashtable values = new Hashtable();
            values.Add("name", "Fire");

            if (isFire == "1")
            {

                values.Add("fireData", isFire + "|" + _motor.Gun.RecoiledDirection.x + "|" + _motor.Gun.RecoiledDirection.y + "|" + _motor.Gun.RecoiledDirection.z +
                    "|" + _motor.Gun.TempraycastOrigin.x + "|" + _motor.Gun.TempraycastOrigin.y + "|" + _motor.Gun.TempraycastOrigin.z);
            }
            else
            {
                values.Add("fireData", isFire + "|" + "");
            }
            MyClient.send(MySerialize.toBytes(values));
        }

        public void aimRelealeEvent(string isAim)
        {
            Hashtable values = new Hashtable();
            values.Add("name", "Aim");
            values.Add("AimData", isAim);
            MyClient.send(MySerialize.toBytes(values));
        }

        public void SynLocationEvent()
        {
            Hashtable values = new Hashtable();
            values.Add("name", "SynLocation");
            values.Add("LocData", transform.position.x + "|" + transform.position.y + "|" + transform.position.z);
            MyClient.send(MySerialize.toBytes(values));
        }

        public void SwitchWeaponEvent()
        {
            Hashtable values = new Hashtable();
            values.Add("name", "SwitchWeapon");
            values.Add("WeaponData", _motor.CurrentWeapon+"");
            MyClient.send(MySerialize.toBytes(values));
        }

        public void SynClimbingEvent()
        {
            Hashtable values = new Hashtable();
            values.Add("name", "SynClimbing");
            values.Add("ClimbingData", "");

            if (otp != null)
            {
                otp.UpdateClimbing();
            }
            MyClient.send(MySerialize.toBytes(values));
        }
        public void SynJumpEvent()
        {
            Hashtable values = new Hashtable();
            values.Add("name", "SynJump");
            values.Add("JumpData", _motor._jumpAngle +"");
            if (otp != null)
            {
                //otp.UpdateJumping(_motor._jumpAngle);
            }
            MyClient.send(MySerialize.toBytes(values));
        }
        public void SynRollingEvent()
        {
            Hashtable values = new Hashtable();
            values.Add("name", "SynRolling");
            values.Add("RollingData", _motor._rollAngle+"|"+ transform.localEulerAngles.y+"|"+ transform.position.x + "|" + transform.position.y + "|" + transform.position.z);
            if (otp != null)
            {
                otp.UpdateRolling(_motor._rollAngle);
            }
            MyClient.send(MySerialize.toBytes(values));
        }
    }
}